package com.gwctv.handler;

import com.gwctv.constant.MessageConstant;
import com.gwctv.exception.BaseException;
import com.gwctv.result.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.sql.SQLIntegrityConstraintViolationException;

/**
 * @RestControllerAdvice 定义全局异常处理器
 * @RestControllerAdvice注解 此注解底层封装@ResponseBody注解，保证了全局异常处理器响应给前端的异常
 * 数据为json格式的字符串
 * 全局异常处理器的原理：
 * 1.如果没有异常处理器异常的处理机制：浏览器发送请求到controller层、service、dao层，如果遇到异常，那么
 * 异常会逆方向向顶层抛，即dao层抛向service层，service层抛给controller层，最终controller层抛给前端。
 * 这种自然向前端抛错误的方式会造成响应数据的不统一；因为错误的类型不一样，响应给前端的数据也就不一样。
 * 2.为了统一处理异常数据，将异常数据格式也统一为Result，所以就有了全局异常处理器
 * 全局异常处理器的原理就是各层出现的异常向上抛的时候，最终会抛给controller层，这时候如果是异常数据，
 * 也会将异常抛给全局异常处理器，对异常进行统一处理再响应给前端；如果是正常数据抛给controller层后，
 * controller层将直接响应给前端。
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * @param bx 自定义异常类形参
     * @return 返回错误的Result对象结果
     * @ExceptionHandler 标识方法用于处理异常
     * 此注解中的value属性可以指定此方法要处理何种异常，如果不指定，此注解标准此方法是异常处理方法
     */
    @ExceptionHandler
    public Result exceptionHandler(BaseException bx) {
        // getMessage()是继承自父类中方法
        return Result.error(bx.getMessage());
    }

    /**
     * 处理sql异常
     * @param ex
     * @return
     */
    @ExceptionHandler
    public Result exceptionHandler(SQLIntegrityConstraintViolationException ex) {
        // Duplicate entry 'zhangsan' for key 'employee.idx_username'
        String message = ex.getMessage();
        if (message.contains("Duplicate entry")) {
            String[] split = message.split(" ");
            String username = split[2];
            String msg = username + MessageConstant.ALREADY_EXISTS;
            return Result.error(msg);
        }else{
            return Result.error(MessageConstant.UNKNOWN_ERROR);
        }
    }
}
